package ace.module.stock.core.impl.service.impl;

import ace.cmp.util.AceStreamUtils;
import ace.module.common.api.model.input.TenantAndAppTypeInput;
import ace.module.stock.api.model.dto.WmsSalesQuantityDto;
import ace.module.stock.api.model.dto.WmsStockDto;
import ace.module.stock.api.model.dto.ext.WmsStockAndSalesQuantityDto;
import ace.module.stock.api.model.input.WmsBizInitInput;
import ace.module.stock.api.model.input.WmsBizParentIdInput;
import ace.module.stock.api.model.input.WmsBizUniqueIdInput;
import ace.module.stock.core.impl.dao.entity.WmsApplication;
import ace.module.stock.core.impl.manager.WmsApplicationManager;
import ace.module.stock.core.impl.manager.WmsSalesQuantityManager;
import ace.module.stock.core.impl.manager.WmsStockManager;
import ace.module.stock.core.impl.service.WmsStockAndSalesQuantityService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * .
 *
 * @author Caspar
 */
@Slf4j
@AllArgsConstructor
@Component
public class WmsStockAndSalesQuantityServiceImpl implements WmsStockAndSalesQuantityService {

  private final WmsStockManager wmsStockManager;
  private final WmsSalesQuantityManager wmsSalesQuantityManager;
  private final WmsApplicationManager wmsApplicationManager;

  @Transactional(rollbackFor = Throwable.class)
  @Override
  public void initOrSetStockAndInitOrNoneSalesQuantity(TenantAndAppTypeInput<WmsBizInitInput> input) {
    WmsApplication wmsApplication = wmsApplicationManager.getAndCheckByOutIdAndOutType(input.getTenantId().toString(), input.getType());
    this.wmsStockManager.initOrSet(wmsApplication, input.getData());
    this.wmsSalesQuantityManager.initOrNone(wmsApplication, input.getData());
  }

  @Override
  public List<WmsStockAndSalesQuantityDto> getDtoByBizUniqueIdIn(TenantAndAppTypeInput<List<WmsBizUniqueIdInput>> input) {
    WmsApplication wmsApplication = wmsApplicationManager.getByOutIdAndOutType(input.getTenantId().toString(), input.getType());

    if (Objects.isNull(wmsApplication)) {
      return new ArrayList<>();
    }

    List<WmsStockDto> wmsStockDtos = wmsStockManager.getDtoByWmsAppIdAndBizUniqueIdIn(wmsApplication.getId(), input.getData());

    List<WmsSalesQuantityDto> wmsSalesQuantityDtos = wmsSalesQuantityManager.getDtoListByWmsAppIdAndBizUniqueIdIn(wmsApplication.getId(), input.getData());

    return this.convert(wmsStockDtos, wmsSalesQuantityDtos);
  }

  @Override
  public List<WmsStockAndSalesQuantityDto> getDtoByBizParentIdIn(TenantAndAppTypeInput<WmsBizParentIdInput> bizParentIdInput) {
    throw new NotImplementedException();
//    WmsApplication wmsApplication = wmsApplicationManager.getByOutIdAndOutType(bizParentIdInput.getTenantId().toString(), bizParentIdInput.getType());
//
//    if (Objects.isNull(wmsApplication)) {
//      return new ArrayList<>();
//    }
//
//    List<WmsStockDto> wmsStockDtos = wmsStockManager.getDtoListByWmsAppIdAndBizParentId(wmsApplication.getId(), bizParentIdInput.getData());
//
//    List<WmsSalesQuantityDto> wmsSalesQuantityDtos = wmsSalesQuantityManager.getDtoListByWmsAppIdAndBizParentId(wmsApplication.getId(), bizParentIdInput.getData());
//
//    return this.convert(wmsStockDtos, wmsSalesQuantityDtos);
  }

  private List<WmsStockAndSalesQuantityDto> convert(List<WmsStockDto> wmsStockDtos, List<WmsSalesQuantityDto> wmsSalesQuantityDtos) {
    Map<String, WmsBizUniqueIdInput> bizUniqueIdMap = new HashMap<>();
    AceStreamUtils.ofNullable(wmsStockDtos)
        .forEach(wmsStockDto -> {
          String bizUniqueIdString = String.format("%s%s", wmsStockDto.getObjectId(), wmsStockDto.getObjectType());
          WmsBizUniqueIdInput bizUniqueId = WmsBizUniqueIdInput.builder()
              .objectType(wmsStockDto.getObjectType())
              .objectId(wmsStockDto.getObjectId())
              .build();
          if (bizUniqueIdMap.containsKey(bizUniqueIdString)) {
            return;
          }
          bizUniqueIdMap.put(bizUniqueIdString, bizUniqueId);
        });

    AceStreamUtils.ofNullable(wmsSalesQuantityDtos)
        .forEach(wmsSalesQuantityDto -> {
          String bizUniqueIdString = String.format("%s%s", wmsSalesQuantityDto.getObjectId(), wmsSalesQuantityDto.getObjectType());

          WmsBizUniqueIdInput bizUniqueId = WmsBizUniqueIdInput.builder()
              .objectType(wmsSalesQuantityDto.getObjectType())
              .objectId(wmsSalesQuantityDto.getObjectId())
              .build();
          if (bizUniqueIdMap.containsKey(bizUniqueIdString)) {
            return;
          }
          bizUniqueIdMap.put(bizUniqueIdString, bizUniqueId);
        });

    return bizUniqueIdMap.entrySet()
        .stream()
        .map(entry -> {
          WmsBizUniqueIdInput wmsBizUniqueIdInput = entry.getValue();
          WmsStockDto wmsStockDto = wmsStockManager.findDtoByBizUniqueId(wmsStockDtos, wmsBizUniqueIdInput);
          WmsSalesQuantityDto wmsSalesQuantityDto = wmsSalesQuantityManager.findDtoByBizUniqueId(wmsSalesQuantityDtos, wmsBizUniqueIdInput);
          return WmsStockAndSalesQuantityDto.builder()
              .stock(wmsStockDto)
              .salesQuantity(wmsSalesQuantityDto)
              .build();
        })
        .collect(Collectors.toList());
  }
}